<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <div>
            根实例：
            <div>count - {{count}} </div>
            <div>doneTodos - {{doneTodos}}</div>
            <div>doneTodosCount - {{doneTodosCount}}</div>
            <div>getTodoById2 - {{getTodoById(2)}}</div>
            <button @click="clickButtonAdd">点击+1(mutations)</button>
            <button @click="clickButtonActionsAdd">点击+1(actions)</button>
            <div>{{obj}}</div>
            <button @click="clickModifyObj">点击增加obj属性</button>
        </div>
        <counter></counter>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
    <script src="https://unpkg.com/vuex"></script>

    <!-- store容器 -->
    <script>
        const store = new Vuex.Store({
            state: {
                count: 0,
                todos: [
                    { id: 1, text: '...', done: true },
                    { id: 2, text: '...', done: false },
                    { id: 3, text: '...', done: true },
                    { id: 4, text: '...', done: false }
                ],
                obj: {
                    name: 'lst'
                }
            },
            getters: {
                doneTodos: state => {
                    return state.todos.filter(todo => todo.done)
                },
                doneTodosCount: (state, getters) => {
                    return getters.doneTodos.length
                },
                getTodoById: (state) => (id) => {
                    return state.todos.find(todo => todo.id === id)
                }
            },
            mutations: {
                increment(state, payload) {
                    state.count += payload.num;
                },
                sub(state) {
                    state.count--;
                },
                modifyObj(state) {
                    // 给对象添加新属性
                    // state.obj.sex = '女' //无效
                    // Vue.set(state.obj, 'sex', '女') //有效
                    state.obj = { ...state.obj, 'sex': '女' } //有效

                }
            },
            actions: {
                // Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象
                // increment(context) {
                //     context.commit('increment')
                // }
                // 利用参数解构简化代码
                // increment({ commit }, payload) {
                //     setTimeout(() => {
                //         commit('increment', payload)
                //     }, 5000)
                // }

                increment({ commit }, payload) {
                    return new Promise((resolve, reject) => {
                        setTimeout(() => {
                            commit('increment', payload);
                            resolve()
                        }, 5000)
                    })
                }

            }
        })
    </script>

    <!-- 组件 -->
    <script>
        // 创建一个 Counter 组件
        const Counter = {
            template: `<div>
                    Counter 组件： {{ count }} - {{countAlias}}
                    </br>
                    {{countPlusLocalState}}
                    <br/>
                    <button @click="clickButtonSub">点击-1</button>
                    <button @click="add({num:1})">点击+1</button>
                    <div>doneTodos - {{doneTodos}}</div>
                    <div>doneTodosCount - {{doneTodosCount}}</div>
                    <div>getTodoById2 - {{getTodoById(2)}}</div>
                       </div>`,
            data() {
                return {
                    localCount: 10
                }

            },
            computed: {
                ...Vuex.mapState({
                    // 箭头函数可使代码更简练
                    count: state => state.count,

                    // 传字符串参数 'count' 等同于 `state => state.count`
                    countAlias: 'count',

                    // 为了能够使用 `this` 获取局部状态，必须使用常规函数
                    countPlusLocalState(state) {
                        return state.count + this.localCount
                    }
                }),
                ...Vuex.mapGetters({
                    doneTodos: 'doneTodos',
                    doneTodosCount: 'doneTodosCount',
                    getTodoById: 'getTodoById'
                })
            },
            methods: {
                ...Vuex.mapMutations({
                    sub: 'sub' // 将 `this.sub()` 映射为 `this.$store.commit('sub')`
                }),
                clickButtonSub() {
                    console.log('clickButtonSub');
                    this.sub();
                    console.log(this.$store.state.count)
                },
                ...Vuex.mapActions({
                    add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
                })
            }

        }
    </script>

    <!-- 根实例 -->
    <script>
        new Vue({
            el: '#app',
            store: store,
            components: { Counter },
            data() {
                return {
                    // count: this.$store.state.count //vuex的state里面的数据要放在computed里监听，才能实现响应式
                }
            },
            computed: {
                count() {
                    return this.$store.state.count
                },
                doneTodos() {
                    return this.$store.getters.doneTodos
                },
                obj() {
                    return this.$store.state.obj
                },
                doneTodosCount() {
                    return this.$store.getters.doneTodosCount
                },
                getTodoById() {
                    return this.$store.getters.getTodoById;
                }
            },
            methods: {
                clickButtonAdd() {
                    console.log('clickButtonAdd');
                    this.$store.commit('increment', { num: 1 });
                    console.log(this.$store.state.count)
                },
                clickModifyObj() {
                    console.log('clickModifyObj')
                    this.$store.commit('modifyObj');
                },
                clickButtonActionsAdd() {
                    this.$store.dispatch('increment', { num: 1 }).then(() => {
                        console.log('异步操作执行完')
                    })
                }
            }
        })
    </script>
</body>

</html>